package com.caipiao.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.slf4j.Logger;

/**
 * <p>
 * Title: String常用的函数
 * </p>
 * 
 * <p>
 * Description: String常用的函数
 * </p>
 * 
 * <p>
 * </p>
 * 
 * <p>
 * File Name: StringTools.java
 * </p>
 * 
 * @author
 * @version
 */
public class StringTools
{
	// Byte to short
	public static short getShort(byte[] b, int index)
	{
		return (short) (((b[index] << 8) | b[index + 1] & 0xff));
	}

	public static void putShort(byte b[], short s, int index)
	{
		b[index] = (byte) (s >> 8);
		b[index + 1] = (byte) (s >> 0);
	}

	// byte to short
	public static short ByteToShort(byte bNum)
	{
		if (bNum >= 0)
		{
			return (short) bNum;
		} else
		{
			return (short) (bNum + 256);
		}
	}

	// byte to int
	public static int ByteToInt(byte iNum)
	{
		if (iNum >= 0)
		{
			return (int) iNum;
		} else
		{
			return (int) (iNum + 256);
		}
	}

	// Short网络序转本地序
	public static short ntohs(byte[] byteValue)
	{
		short shortValue = 0;

		try
		{
			shortValue = (short) ((ByteToShort(byteValue[0])) << 8);
			shortValue += ByteToShort(byteValue[1]);
		} catch (Exception e)
		{
			// TraceLogger.getInstance.error("Short网络序转本地序 异常", e, false);
		}
		return shortValue;
	}

	// Int网络序转本地序
	public static int ntohl(byte[] byteValue)
	{
		int intValue = 0;

		try
		{
			intValue = (int) ((ByteToInt(byteValue[0])) << 24);
			intValue += (int) ((ByteToInt(byteValue[1])) << 16);
			intValue += (int) ((ByteToInt(byteValue[2])) << 8);
			intValue += (int) (ByteToInt(byteValue[3]));
		} catch (Exception e)
		{
			// TraceLogger.getInstance.error("Int网络序转本地序 异常", e, false);
		}

		return intValue;
	}

	// int 本地序转为网络序
	public static byte[] htonl(int n)
	{
		byte[] b = new byte[4];
		b[3] = (byte) (n & 0xff);
		b[2] = (byte) (n >> 8 & 0xff);
		b[1] = (byte) (n >> 16 & 0xff);
		b[0] = (byte) (n >> 24 & 0xff);
		return b;
	}

	// short 本地序转为网络序
	public static byte[] htons(short n)
	{
		byte[] b = new byte[2];
		b[1] = (byte) (n & 0xff);
		b[0] = (byte) (n >> 8 & 0xff);
		return b;
	}

	public static int num = 10000;
	public static int lotteryNum = 100;
	public static int serialNum = 100000;

	public static byte[] hexStringToByte(String hex)
	{
		int len = (hex.length() / 2);
		byte[] result = new byte[len];
		char[] achar = hex.toUpperCase().toCharArray();
		for (int i = 0; i < len; i++)
		{
			int pos = i * 2;
			result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
		}
		return result;
	}

	private static byte toByte(char c)
	{
		byte b = (byte) "0123456789ABCDEF".indexOf(c);
		return b;
	}

	/** */
	/**
	 * 把字节数组转换成16进制字符串
	 * 
	 * @param bArray
	 * @return
	 */
	public static final String bytesToHexString(byte[] bArray)
	{
		StringBuffer sb = new StringBuffer(bArray.length);
		String sTemp;
		for (int i = 0; i < bArray.length; i++)
		{
			sTemp = Integer.toHexString(0xFF & bArray[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		return sb.toString();
	}

	/** */
	/**
	 * 把字节数组转换为对象
	 * 
	 * @param bytes
	 * @return
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public static final Object bytesToObject(byte[] bytes) throws IOException,
			ClassNotFoundException
	{
		ByteArrayInputStream in = new ByteArrayInputStream(bytes);
		ObjectInputStream oi = new ObjectInputStream(in);
		Object o = oi.readObject();
		oi.close();
		return o;
	}

	/** */
	/**
	 * 把可序列化对象转换成字节数组
	 * 
	 * @param s
	 * @return
	 * @throws IOException
	 */
	public static final byte[] objectToBytes(Serializable s) throws IOException
	{
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ObjectOutputStream ot = new ObjectOutputStream(out);
		ot.writeObject(s);
		ot.flush();
		ot.close();
		return out.toByteArray();
	}

	public static final String objectToHexString(Serializable s)
			throws IOException
	{
		return bytesToHexString(objectToBytes(s));
	}

	public static final Object hexStringToObject(String hex)
			throws IOException, ClassNotFoundException
	{
		return bytesToObject(hexStringToByte(hex));
	}

	/** */
	/**
	 * @函数功能: BCD码转为10进制串(阿拉伯数据)
	 * @输入参数: BCD码
	 * @输出结果: 10进制串
	 */
	public static String bcd2Str(byte[] bytes)
	{
		StringBuffer temp = new StringBuffer(bytes.length * 2);

		for (int i = 0; i < bytes.length; i++)
		{
			temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
			temp.append((byte) (bytes[i] & 0x0f));
		}
		return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp
				.toString().substring(1) : temp.toString();
	}

	/** */
	/**
	 * @函数功能: 10进制串转为BCD码
	 * @输入参数: 10进制串
	 * @输出结果: BCD码
	 */
	public static byte[] str2Bcd(String asc)
	{
		int len = asc.length();
		int mod = len % 2;

		if (mod != 0)
		{
			asc = "0" + asc;
			len = asc.length();
		}

		byte abt[] = new byte[len];
		if (len >= 2)
		{
			len = len / 2;
		}

		byte bbt[] = new byte[len];
		abt = asc.getBytes();
		int j, k;

		for (int p = 0; p < asc.length() / 2; p++)
		{
			if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9'))
			{
				j = abt[2 * p] - '0';
			} else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z'))
			{
				j = abt[2 * p] - 'a' + 0x0a;
			} else
			{
				j = abt[2 * p] - 'A' + 0x0a;
			}

			if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9'))
			{
				k = abt[2 * p + 1] - '0';
			} else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z'))
			{
				k = abt[2 * p + 1] - 'a' + 0x0a;
			} else
			{
				k = abt[2 * p + 1] - 'A' + 0x0a;
			}

			int a = (j << 4) + k;
			byte b = (byte) a;
			bbt[p] = b;
		}
		return bbt;
	}

	/** */
	/**
	 * @函数功能: BCD码转ASC码
	 * @输入参数: BCD串
	 * @输出结果: ASC码
	 */
	// public static String BCD2ASC(byte[] bytes) {
	// StringBuffer temp = new StringBuffer(bytes.length * 2);
	//
	// for (int i = 0; i < bytes.length; i++) {
	// int h = ((bytes[i] & 0xf0) >>> 4);
	// int l = (bytes[i] & 0x0f);
	// temp.append(BToA[h]).append( BToA[l]);
	// }
	// return temp.toString() ;
	// }

	/** */
	/**
	 * MD5加密字符串，返回加密后的16进制字符串
	 * 
	 * @param origin
	 * @return
	 */
	public static String MD5EncodeToHex(String origin)
	{
		return bytesToHexString(MD5Encode(origin));
	}

	/** */
	/**
	 * MD5加密字符串，返回加密后的字节数组
	 * 
	 * @param origin
	 * @return
	 */
	public static byte[] MD5Encode(String origin)
	{
		return MD5Encode(origin.getBytes());
	}

	/** */
	/**
	 * MD5加密字节数组，返回加密后的字节数组
	 * 
	 * @param bytes
	 * @return
	 */
	public static byte[] MD5Encode(byte[] bytes)
	{
		// System.out.println(bytesToHexString(bytes));
		MessageDigest md = null;
		try
		{
			md = MessageDigest.getInstance("MD5");
			return md.digest(bytes);
		} catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
			return new byte[0];
		}
	}
	
	//检查数字
	public static int GetInteger(String value)
	{
		try
		{
			return Integer.valueOf(value);
		}
		catch(Exception e)
		{
			return -1;
		}
	}
	
	public static boolean CheckPhone(String phone)
	{
		//中文字母开头,允许数字和字母下划线
		if (null != phone && phone.matches("^1[3-8]+\\d{9}"))
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	//校验密码格式
	public static boolean CheckMD5Password(String password) throws Exception
	{
		if (null == password || !password.matches("[a-f A-F 0-9]{32}"))
		{
			return false;
		}
		return true;
	}
	
	public static boolean CheckRealName(String realName) throws Exception
	{
		//2~5个中文
		 if (null != realName && realName.matches("[\u4E00-\u9FA5]{2,8}"))
		 {
			 return true;
		 }
		 else
		 {
			 return false;
		 }
	}
	
	public static boolean CheckUserName(String userName) throws Exception
	{
		//中文字母开头,允许数字和字母下划线
		 if (null != userName && userName.matches("[\u4E00-\u9FA5a-zA-Z]{1}[\u4E00-\u9FA5a-zA-Z0-9]{2,15}"))
		 {
			 return true;
		 }
		 else
		 {
			 return false;
		 }
	}
	
	//隐藏用户手机号及UID
	public static String MaskUserNameLong(String userName)
	{
		if (userName.matches("^1[3-8]+\\d{9}"))	//手机号
		{
			return StringTools.MaskString(userName, "*", 3, 3);
		}
		else if (userName.matches("[0-9]{2,15}"))	//UID
		{
			return StringTools.MaskString(userName, "*", 2, 2);
		}
		else
		{
			try
			{
				if (userName.getBytes("GBK").length >12)
				{
					return StringTools.MaskString(userName, "*", 3, 2);
				}
			}
			catch(Exception e)
			{}
		}
		return userName;
	}
	
	//隐藏用户手机号及UID
	public static String MaskUserName(String userName)
	{
		if (userName.matches("^1[3-8]+\\d{9}"))	//手机号
		{
			return StringTools.MaskString(userName, "*", 3, 3);
		}
		else if (userName.matches("[0-9]{2,15}"))	//UID
		{
			return StringTools.MaskString(userName, "*", 2, 2);
		}
		
		return userName;
	}
	
	//1留头隐尾 2留尾隐头 3留头尾隐中间
	public static String MaskString(String str, String mask_str, int type, int maxShow)
	{
		if (null == str || str.isEmpty())
		{
			return str;
		}
		
		if (str.length() == 1)
		{
			return mask_str;
		}
		
		if (str.length() == 2)
		{
			if (type == 2)
			{
				return  "*" + str.substring(1, 2);
			}
			return str.substring(0, 1) + "*";
		}
		
		int str_len = str.length();
		
		int sublen = (int)str_len/3;
		
		if (sublen > maxShow)
		{
			sublen = maxShow;
		}
		
		String mask = "";
		
		int MaskLen = sublen;
		if (MaskLen > 4)
		{
			MaskLen = 4;
		}
		
		for (int i=0; i<MaskLen;++i)
		{
			mask += mask_str;
		}
		
		if (type == 1)
		{
			return str.substring(0, sublen) + mask;
		}
		
		if (type == 2)
		{
			return mask + str.substring(str_len-sublen, str_len);
		}
		
		if (type == 3)
		{
			return str.substring(0, sublen) + mask + str.substring(str_len-sublen, str_len);
		}

		return str;
	}
	
	//字符串过滤
	public static String Trim(String str)
	{
		if (null == str || str.isEmpty())
		{
			return str;
		}
		return str.replace("\r\n", "").trim();
	}
	
	static final BigDecimal yuan_fen_times = BigDecimal.valueOf(100);
	public static long RMB_Yun2Fen(String yuan)
	{
		BigDecimal yuan_ = new BigDecimal(yuan);
		BigDecimal fen = yuan_.multiply(yuan_fen_times);
		return fen.longValue();
	}
	
	public static double RMB_Fen2Yuan(String fen)
	{
		
		BigDecimal fen_ = new BigDecimal(fen);
		BigDecimal yuan = fen_.divide(yuan_fen_times);
		return yuan.doubleValue();
	}
	
	public static double RMB_Fen2Yuan(long fen)
	{
		BigDecimal fen_ = new BigDecimal(fen);
		BigDecimal yuan = fen_.divide(yuan_fen_times);
		return yuan.doubleValue();
	}
	
	public static String GetMoneyDesc(long money_wan)
	{
		String value = "";
		
		long yi = money_wan/10000;
		if (yi > 0)
		{
			value = yi + "亿";
		}
		
		long left = money_wan - yi*10000;
		
		if (left > 0)
		{
			value = value + left + "万";
		}
		
		return value;
	}
	
	//存储文件
	public static void saveToFile(String content, String local_file_path, boolean rename_exist_file, Logger logger)
	{
		boolean save_result = false;
		
		File local_file = null;		
        FileOutputStream localFileStream = null;
        try
        {
        	local_file = new File(local_file_path);
        	if (local_file.exists())	//文件已存在
        	{
        		// 日志文件已存在
        		logger.warn("本地文件已存在:" + local_file_path);
        		
        		if (rename_exist_file)
        		{
        			String rename_path = local_file_path + "." + IdMaker.Get_Random_Id(16) + ".bak";
        			File rename_file = new File(rename_path);
        			
        			if (local_file.renameTo(rename_file))	//重命名成功
        			{
        				//重命名成功
        				logger.warn("本地文件重命名成功:" + rename_path);
        			}
        			else
        			{
        				//重命名失败
        				throw new Exception("本地文件重命名失败:" + rename_path);
        			}
        		}
        		else	//不重命名
        		{
        			throw new Exception("本地文件已存在,未重命名:" + local_file_path);
        		}
    		}
        	else
        	{
        		String parent_path = local_file.getParent();
        		File parent_dir = new File(parent_path);
        		
        		//上级目录不存在,生成
        		if (!parent_dir.exists())
        		{
        			parent_dir.mkdirs();
        		}
        	}
        	
        	localFileStream = new FileOutputStream(local_file_path);
        	
        	localFileStream.write(content.getBytes());
        	
        	save_result = true;
        }
        catch (Exception e) 
        { 
            //出现异常
        	logger.error("存储异常:" + e.toString());
        } 
        finally
        {
            try 
            { 
                if(localFileStream != null)
                {
                    localFileStream.flush();
                    localFileStream.close();
                }
                
                if (!save_result)	//存储失败
                {
                	local_file = new File(local_file_path);
                	if (local_file.exists())
                	{
                		local_file.delete();
                		logger.trace("存储失败,清理临时文件成功");
                	}
                }
            } 
            catch (Exception e) 
            { 
                //出现异常
            	logger.error("存储失败,finally异常:" + e.toString());
            } 
        }
	}
	
	/**
	 * 对输入的字符串进行倒序排列
	 * 
	 * @param input 需要倒序的字符串
	 * @return 倒序后的字符串
	 */
	public static String reverseString(String input) {
		if (input == null || input.length() <= 1) {
			return input;
		}
		
		StringBuilder sb = new StringBuilder();
		for (int i = input.length() - 1; i >= 0; i--) {
			sb.append(input.charAt(i));
		}
		
		return sb.toString();
	}

}
